文章目录
  1. 1. 函数基础
  2. 2. 递归
  3. 3. 柯里化(Curry)
  4. 4. 闭包
  5. 5. 模块
  6. 6. 数组

这里是关于自己看JS语言精粹函数与数组方面的笔记,记得并不全面,是一些关于自己不太清楚的点。以后随着学习也可以继续补充。
所谓编程,就是将一组需求分解成一组函数与数据结构(的技能)。

函数基础

1.对象字面量产生的对象连接到 Object.prototype;函数对象连接到Function.prototype(然后这个原型对象本身连接到Object.prototype)
2.调用一个函数会暂停当前函数的执行,传递控制权和参数给新的函数。除了声明时定义的形式参数,每个函数还接收两个附加的参数:this 和 arguments。 关于this的解释见 JS中的this总结
3.arguments 函数可以通过此参数访问所有它被调用时传递给它的参数列表,包括那些没有被分配给函数声明时定义的形式参数的多余参数。这样就可以编写一个无须指定参数个数的函数成为可能。

1
2
3
4
5
6
7
8
var sum = function(){
var i,sum =0;
for(i=0;i<arguments.length;i+=1){
sum+=arguments[i];
}
return sum;
}
console.log(sum(1,2,3,4,5))

arguments只是一个类似数组的对象,只有一个length属性,但没有任何数组的方法。
4.调用一个函数会暂停当前函数的执行,传递控制权和参数给新的函数。当一个函数被调用时,它从第一个语句开始执行,并在遇到关闭函数的}结束,然后把控制权交还给调用该函数的程序。return 可提前返回。一个函数总会返回一个值,若没有指定返回值,则返回undefined。如果函数是通过new操作符进行调用的,且返回值不是一个对象,则返回this(该新对象)。
5.扩充功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Function.prototype.method = function (name,func){
if(!this.prototype[name]){
this.prototype[name] = func;
}
return this;
}
//添加一个方法提取数字中的整数部分
Number.method('integer',function(){
return Math[this < 0 ? 'ceil' : 'floor'](this);
})
//添加一个移除字符串首尾空白的方法。
Sting.method('trim',function(){
return this.replace(/^\s+|\s$/g,'');
})

递归

1.递归函数可以高效的操作树形结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var walk_the_DOM = function walk(node,func){
func(node);
node = node.firstChild;
while(node){
walk(node,func);
node = node.nextSibling;
}
}
var getElementsByAttribute = function(att,value){
var results = {};
walk_the_DOM(document.body,function(node){
var actual = node.nodeType ===1 && node.getAttribute(att);
if(typeof actual === 'string' && (actual === value || typeof value !== 'string')){
results.push(node);
}
})
return results;
}

2.尾递归 是一种在函数的最后执行递归调用语句的特殊形式的递归,这意味着如果一个函数返回自身递归调用的结果,那么调用的过程会被替换成一个循环。加速。

柯里化(Curry)

1.柯里化 也为 “局部套用”,是把多参数函数转换成一系列单参数函数并进行调用的技术。柯里化允许我们把函数与传递给它的参数相结合,产生出一个新的函数。

1
2
var add1 = add.curry(1);
console.log(add1(6));//7

js并没有curry方法.

1
2
3
4
5
6
7
8
Function.method('curry',function(){
var slice =Array.prototype.slice,
args = slice.apply(arguments),
that = this;
return function (){
return that.apply(null,args.concat(slice.apply(arguments)));
}
});

闭包

1.函数可以记住并访问所在的词法作用域,就产生了闭包,即使函数在当前词法作用域之外执行。
(* 词法作用域 是由写代码时将变量和块作用域写在哪里决定的,因此放词法分析器处理代码时会保持作用域不变,大部分情况如此)

1
2
3
4
5
6
7
8
9
function foo(){
var a = 2;
function bar(){
console.log(a);
}
return bar;
}
var baz = foo();
baz();//2

在baz函数执行时,foo函数的内部作用域依然存在,并没有被回收。bar()依然持有对该作用域的引用。这个函数在定义时的词法作用域以外的地方被调用,闭包使得函数可以继续访问定义时的此法作用域。无论通过何种手段将内部函数传递到所在的词法作用域之外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包。
2.

1
2
3
4
5
for(var i=1;i<5;i++){
setTimeout(function timer(){
console.log(i);
},1000);
}//每隔1s输出6

尽管循环中的五个函数是在各个迭代中分别定义的,但是这些都被封闭在一个共享的全局作用域中,因此只有一个i. 因此需要更多的闭包作用域。

1
2
3
4
5
6
7
for(var i=1;i<=5;i++){
(function(j){
setTimeout(function timer(){
console.log(j);
},1000);
})(i);
}// 1,2,3,4,5

在迭代内由于函数执行会为每个迭代都生成一个新的作用域,使得延迟函数的回调可以将新的作用域封闭在每个迭代内部。

1
2
3
4
5
for(let i=1;i<5;i++){
setTimeout(function timer(){
console.log(i);
},1000);
} //1,2,3,4,5

let 使得变量每次迭代都会声明一次.

模块

1.用函数与闭包来构造模块,模块是一个提供接口却隐藏状态与实现的函数或者对象.
2.给String增加一个方法 deentityify 方法,用来寻找字符串中的html字符实体并把它们替换成对应的字符,这就需要在一个对象中保存字符实体的名字和它们对应的字符。

1
2
3
4
5
6
7
8
9
10
11
12
13
String.method('deentityify',function(){
var entity = {
quot:'"',
lt:'<',
gt:'>'
};
return function(){
return this.place(/&([^&;]+)/g),function(a,b){
var r = entity[b];
return typeof r === 'string' ? r :a;
}
}
}())

这个entity 对象若是放在deentityfy函数中,每次执行时都会有损耗,因为每次执行该函数的时候该字面量都会被求值一次。
3.每个模块都有一个外部的封闭函数,该函数必须至少被调用一次,每次调用都会创建一个新的模块实例。 封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并且可以访问或者修改私有的状态。

  1. 当只需要一个实例时,可以对这个模块进行简单的改进来实现单例模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var foo = (function cool(){
var something = "ss";
var another = [1,2,3];
function doSomething (){
console.log(something);
}
function doAnother (){
console.log(another.join("!"));
}
return {
doSomething:doSomething,
doAnother:doAnother
}
})();
foo.doSomething();
foo.doAnother();

数组

1.JS数组的length是没有上界的,不会发生越界错误。length属性的值是这个数组的最大整数属性名+1。并不一定等于数组里的属性个数。也可以设置length的值,设置更大的length不会给数组分配更多的空间,而把length设小将导致所有下标大于等于length的属性被删除。
2.判断一个对象是否为数组。

1
2
3
var is_array = function (value){
return Object.prototype.toString.apply(value) === "[object Array]";
}

3.数组几个重要的方法

1
2
3
array.join(separator);//将数组构造成字符串
array.slice(start,end);// 对数组的浅复制,返回一个新数组
array.splice(start,deleteCount,item...);// 在原数组上进行 手术。。。

4.字符串几个重要方法

1
2
string.slice(start,end);// 同array
string.split(separator,limit);//将字符串以这个separator分割成片段组成数组

文章目录
  1. 1. 函数基础
  2. 2. 递归
  3. 3. 柯里化(Curry)
  4. 4. 闭包
  5. 5. 模块
  6. 6. 数组